#include "Overseer.h"
#include "InputManager.h"
#include "GUIManager.h"
#include "State.h"

template<> Overseer* Ogre::Singleton<Overseer>::ms_Singleton = 0;

Overseer::Overseer()
{
	running = false;
}

bool Overseer::initialise()
{
	root = new Ogre::Root();
	if (!root->showConfigDialog()) return false;
	window = root->initialise(true, "Fortress Overseer v0.70");
	Ogre::WindowEventUtilities::addWindowEventListener(window,this);
	running = true;
	setupResources();
	inputManager = new InputManager();
	inputManager->initialise(window);
	guiManager = new GUIManager();
	guiManager->initialise();
	inputManager->addKeyListener(guiManager,"GUIManager");
	inputManager->addMouseListener(guiManager,"GUIManager");
	return true;
}

void Overseer::setupResources()
{
	Ogre::ConfigFile cf;
	cf.load("resources.cfg");
	
	Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator();

	Ogre::String secName, typeName, archName;
	while (seci.hasMoreElements())
	{
		secName = seci.peekNextKey();
		Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
		Ogre::ConfigFile::SettingsMultiMap::iterator i;
		for (i = settings->begin(); i != settings->end(); ++i)
		{
			typeName = i->first;
			archName = i->second;
			Ogre::ResourceGroupManager::getSingletonPtr()->addResourceLocation(archName,typeName,secName);
		}
	}
	Ogre::TextureManager::getSingletonPtr()->setDefaultNumMipmaps(5);
}

bool Overseer::isRunning()
{
	return running;
}

void Overseer::update()
{
	Ogre::WindowEventUtilities::messagePump();
	Ogre::Real timeSinceLastFrame = (timer.getMilliseconds()-lastTime)/1000.0f;
	lastTime = (Ogre::Real)timer.getMilliseconds();
	inputManager->capture();
	guiManager->update(timeSinceLastFrame);
	stateMutex.lock();
	if (!states.empty()) states.back()->update(timeSinceLastFrame); //no state operations in here!
	stateMutex.unlock();
	root->renderOneFrame();
}

void Overseer::changeState(State *s)
{
	boost::mutex::scoped_lock lock(stateMutex); //NOTE: This mutex means that the main thread CANNOT do state operations in state update functions!
	if (!states.empty())
	{
		states.back()->exit();
		states.pop_back();
	}
	states.push_back(s);
	states.back()->initialise();
	inputManager->addKeyListener(s,s->getName());
	inputManager->addMouseListener(s,s->getName());
}

void Overseer::pushState(State *s)
{
	boost::mutex::scoped_lock lock(stateMutex);
	if (!states.empty()) states.back()->pause();
	states.push_back(s);
	states.back()->initialise();
	inputManager->addKeyListener(s,s->getName());
	inputManager->addMouseListener(s,s->getName());
}

void Overseer::popState()
{
	boost::mutex::scoped_lock lock(stateMutex);
	if (!states.empty())
	{
		inputManager->removeKeyListener(states.back()->getName());
		inputManager->removeMouseListener(states.back()->getName());
		states.back()->exit();
		states.pop_back();
	}
	if (!states.empty()) states.back()->resume();
}

State* Overseer::getCurrentState()
{
	boost::mutex::scoped_lock lock(stateMutex);
	if (!states.empty()) return states.back();
	else return NULL;
}

void Overseer::exit()
{
	running = false;
}

void Overseer::cleanup()
{
	inputManager->removeAllKeyListeners();
	inputManager->removeAllMouseListeners();
	while (!states.empty())
	{
		states.back()->exit();
		states.pop_back();
	}
}

GUIManager* Overseer::getGUIManager()
{
	return guiManager;
}

InputManager* Overseer::getInputManager()
{
	return inputManager;
}

void Overseer::windowClosed(Ogre::RenderWindow *rw)
{
	exit();
}

void Overseer::windowResized(Ogre::RenderWindow *rw)
{
	inputManager->setWindowSize(rw->getWidth(), rw->getHeight());
	guiManager->setWindowSize(rw->getWidth(), rw->getHeight());
}

void Overseer::windowFocusChange(Ogre::RenderWindow *rw)
{
}